﻿using OpenTK;
using OpenTK.Graphics.OpenGL;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace OpenTKApp
{
    public partial class Form1 : Form
    {
        Camera camera;
        Point? MousePos = null;
        public Form1()
        {
            InitializeComponent();

        }
        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
            this.glControl1.Paint += GlControl1_Paint;
            this.glControl1.MouseDown += GlControl1_MouseDown;
            this.glControl1.MouseUp += GlControl1_MouseUp;
            this.glControl1.MouseMove += GlControl1_MouseMove;
            this.glControl1.MouseWheel += GlControl1_MouseWheel;
            
            GL.ClearColor(0.5f, 0.5f, 0.5f, 0.7f); //背景颜色设置为灰色

            int w = this.glControl1.Width;
            int h = this.glControl1.Height;
            GL.Viewport(0, 0, w, h);  //窗体尺寸设置

            camera = new Camera(new Vector3(3, 0, -1), (float)this.glControl1.Width / (float)this.glControl1.Height);  //相机位置设置
        }


        private void GlControl1_MouseDown(object sender, MouseEventArgs e)
        {
            MousePos = new Point(e.X, e.Y);
        }
        private void GlControl1_MouseUp(object sender, MouseEventArgs e)
        {
            MousePos = null;
        }
        private void GlControl1_MouseMove(object sender, MouseEventArgs e)
        {
            if (MousePos == null) 
            {
                return;
            }
            var deltaX = e.X - MousePos.Value.X;
            var deltaY = e.Y - MousePos.Value.Y;
            MousePos = new Point(e.X, e.Y);

            camera.PitchView((float)(-2 * Math.PI * deltaX / glControl1.Width), (float)(-2 * Math.PI * deltaY / glControl1.Height));

            this.glControl1.Invalidate();
        }

        private void GlControl1_MouseWheel(object sender, MouseEventArgs e)
        {
            camera.Position += e.Delta / Math.Abs(e.Delta) * camera.Front / camera.Front.Length;
            glControl1.Invalidate();
        }

        private void GlControl1_Paint(object sender, PaintEventArgs e)
        {
            GL.Clear(
                    ClearBufferMask.ColorBufferBit |
                    ClearBufferMask.DepthBufferBit |
                    ClearBufferMask.StencilBufferBit);

            GL.MatrixMode(MatrixMode.Modelview);
            GL.LoadIdentity();

            Matrix4 ViewMatrix = camera.GetViewMatrix();
            GL.LoadMatrix(ref ViewMatrix);

            GL.MatrixMode(MatrixMode.Projection);
            Matrix4 ProjMatrix = camera.GetProjectionMatrix();
            GL.LoadMatrix(ref ProjMatrix);

            DrawCube(Color.Orange, new Vector3d(0, 0, 0), new Vector3d(2, 2, 2));

            glControl1.SwapBuffers();
        }
        void DrawCube(Color color, Vector3d refMarker, Vector3d size)
        {
            List<Vector3d> points = new List<Vector3d>(); //points

            //back points (anti-clockwise)
            points.Add(refMarker);
            points.Add(new Vector3d(points[0].X + size.X, points[0].Y, points[0].Z));
            points.Add(new Vector3d(points[0].X + size.X, points[0].Y + size.Y, points[0].Z));
            points.Add(new Vector3d(points[0].X, points[0].Y + size.Y, points[0].Z));

            //front points (anti-clockwise)
            points.Add(new Vector3d(points[0].X, points[0].Y, points[0].Z + size.Z));
            points.Add(new Vector3d(points[1].X, points[1].Y, points[1].Z + size.Z));
            points.Add(new Vector3d(points[2].X, points[2].Y, points[2].Z + size.Z));
            points.Add(new Vector3d(points[3].X, points[3].Y, points[3].Z + size.Z));

            //sequency
            int[] seqs = {
                             0, 1, 2, 3, //back side
                             7, 6, 5, 4, //front side
                             0, 3, 7, 4, //left side
                             5, 6, 2, 1, //right side
                             0, 4, 5, 1, //bottom side
                             2, 3, 7, 6  //tope side
                         };


            GL.ShadeModel(ShadingModel.Smooth);

            GL.Color3(color);
            GL.Begin(BeginMode.Quads);
            foreach (int seq in seqs)
            {
                GL.Vertex3(points[seq]);
            }
            GL.End();

            GL.Color3(Color.GreenYellow);
            GL.Begin(BeginMode.LineStrip);
            foreach (int seq in seqs)
            {
                GL.Vertex3(points[seq]);
            }
            GL.End();

        }
    
    

    }
}
